#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
// #include <malloc.h>

static void CopyToItem(Node *pn, Item *pi);
static void CopyToNode(Item item, Node *node);
void QueueTraverse(const Queue *pqueue, void (*Function)(Node *pnode));

void InitializeQueue(Queue *pq)
{
    //初始化所有的项目<头指针,尾指针为NULL,items项目数为0>
    pq->front = NULL;
    pq->tail = NULL;
    pq->items = 0;
}

bool QueueIsEmpty(const Queue *pq)
{
    return pq->items == 0;
}

bool QueueIsFull(const Queue *pq)
{
    return pq->items == MAXQUEUE;
}

unsigned int QueueItemCount(const Queue *pq)
{
    return pq->items;
}

bool AddItemFromTail(Item item, Queue *pq)
{
    // 排除 过关斩将
    if (QueueIsFull(pq))
    {
        fprintf(stderr, "ERROR! Queue is Full!\n");
        return false;
    }

    Node *pnew = (Node *)malloc(sizeof(Node));
    if (pnew == NULL)
    {
        fprintf(stderr, "Can't allocate full memory!\n");
        exit(-1);
    }

    // Node填充
    CopyToNode(item, pnew);
    pnew->next = NULL;
    // 填充完成 item + NULL;

    if (QueueIsEmpty(pq))
    // 位列队列最前端!
    {
        pq->front = pnew;
    }
    else
    // 不是队列最前端
    {
        pq->tail->next = pnew;
    }
    pq->tail = pnew;
    pq->items++;
    return true;
}

bool DeleteItemFromHead(Item *pitem, Queue *pq)
{
    Node *pt;
    if (QueueIsEmpty(pq))
    {
        return false;
    }

    CopyToItem(pq->front, pitem);

    pt = pq->front;
    // 先将Queue中的头指针进行更改,然后再删除对应的Node指针
    pq->front = pq->front->next;
    free(pt);

    pq->items--;
    if (QueueIsEmpty(pq))
    {
        pq->tail = NULL;
    }
    return true;
}

bool EmptyQueue(Queue *pq)
{
    Item dummy;
    while (!QueueIsEmpty(pq))
    {
        DeleteItemFromTail(&dummy, pq);
    }
    if (QueueIsEmpty(pq))
    {
        return true;
    }
    else
    {
        fprintf(stderr, "ERROR! Queue may be DESTROYED!");
        return false;
    }
}

static void CopyToNode(Item item, Node *node)
{
    node->item = item;
}

static void CopyToItem(Node *pn, Item *pi)
{
    *pi = pn->item;
}

// 怎样在队列中执行这些函数呢?

// const保证了队列指针pqueue不会被修改
/**
 * @brief 在队列中对每一个对象执行传入函数
 *
 * @param pqueue 队列
 * @param Function 传入的想要执行的函数指针
 */
void QueueTraverse(const Queue *pqueue, void (*Function)(Node *pnode))
{
    // 队列为空
    if (QueueIsEmpty(pqueue))
    {
        fprintf(stderr, "ERROR! Queue is EMPTY!\n");
        return;
    }

    // 队列非空  遍历队列中的每一个Node
    // 得到队列中的最开始的Node指针
    Node *pt = pqueue->front;
    // front是队列头指针,next指向下一个对象

    // unsigned int count = 0;
    // do
    // {
    //     Function(pt);
    //     pt = pt->next;
    //     count++;
    // } while (count != QueueItemCount(pqueue));

    do
    {
        // TODO: 函数实现
        Function(pt);
        pt = pt->next;
    } while (pt);
}
